home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / Jim's CDEFs v1.30 / demo Source ƒ / demoDialog.c < prev    next >
Encoding:
Text File  |  1994-11-06  |  24.1 KB  |  884 lines  |  [TEXT/KAHL]

  1. // -----------------------------------------------------------------------------
  2. //    File        : demoDialog.c
  3. //    Date        : August 24, 1994
  4. //    Author        : Jim Stout
  5. //    Purpose        : A demonstration routine for :
  6. //                    - my collection of CDEF's
  7. //                    - dialogAssist.c dialog utilities
  8. //                    - panelAssist.c tabPanel CDEF handling
  9. //                    - movableModal.c dialog routines
  10. //
  11. //    Note the special usage of dim text routines required when using
  12. //    AppendDITL and ShortenDITL routines.  See file dimText.c.
  13. //
  14. //    This demo uses the "TabPanel" CDEF - see "About CDEF's…".
  15. //
  16. // -----------------------------------------------------------------------------
  17. #include <GestaltEqu.h>
  18. #include <stdio.h>
  19.  
  20. // demo routines
  21. #include "demoWind.h"
  22. #include "demoDialog.h"
  23.  
  24. // utility routines
  25.  
  26. #include "dialogAssist.h"
  27. #include "dimText.h"
  28. #include "panelAssist.h"
  29. #include "movableModal.h"
  30. #include "TogLib.h"
  31.  
  32. // cdef #defines
  33.  
  34. #include "jimsCDEF.h"
  35.  
  36. //=============================================================================
  37. // number of controls on each panel
  38. //=============================================================================
  39. #define BUTTONCNT    14
  40. #define POPUPCNT    6
  41. #define SPINNERCNT    8
  42. #define DATECNT        6
  43. #define HSLIDERCNT    5
  44. #define VSLIDERCNT    6
  45. #define PROGBARCNT    9
  46. #define POPEXTCNT    9
  47.  
  48. //=============================================================================
  49. // demoDialog globals - temporary storage for control values
  50. //=============================================================================
  51.  
  52. short gFontNum, gFontSize;
  53. short gButtonValues[BUTTONCNT];
  54. short gPopUpValues[POPUPCNT];
  55. short gSpinnerValues[SPINNERCNT];
  56. long  gDateValues[DATECNT];
  57. short gHSliderValues[HSLIDERCNT];
  58. short gVSliderValues[VSLIDERCNT];
  59. short gProgressValues[PROGBARCNT];
  60. short gPopExtensions[POPEXTCNT];
  61.  
  62. //=============================================================================
  63. // demo the tab dialog panel
  64. //=============================================================================
  65. extern void demoDialog()
  66. {
  67.  
  68.     DialogPtr        theDialog;
  69.     GrafPtr            savePort;
  70.     short            itemHit, inx, currPanel=0,toPanel;
  71.     Handle            h;
  72.     Rect            r;
  73.     Boolean            dimIt = true;
  74.     
  75. // Make sure we have the DITL extensions we need for the PanelSwap()
  76. // routine.  These extensions are present in System 7 but require the
  77. // CommToolbox under System 6.
  78. //
  79. // If you want to use the DITL extensions under System 6, make sure
  80. // you include the CommToolbox libraries and call InitCRM() and
  81. // InitCTBUtilities() after initializing the toolbox.
  82.  
  83.     if(daGestalt(gestaltDITLExtAttr) == -1L) {
  84.         if(daGestalt(gestaltCTBVersion) < 0x0100) {
  85.             StopAlert(256, nil);
  86.             return;
  87.         }
  88.     }
  89.                 
  90.     theDialog = GetNewDialog(128,0L,(DialogPtr)-1);
  91.     if(theDialog) {
  92.         GetPort(&savePort);
  93.         SetPort(theDialog);    
  94.         initDimText(theDialog);                    // set up for dimmable text
  95.         
  96. // initialize the dialog to the correct panel
  97.  
  98.         toPanel = daGetCtlValue(theDialog, TABCNTL);
  99.         
  100.         disposeDimData(theDialog);
  101.         panelSwap(theDialog, 128, currPanel, toPanel, STDCTLS);
  102.         makeDimmable(theDialog);
  103.         
  104. // a "real" application would probably get control settings from some sort
  105. // of configuration file/record/structure.  We'll just initialize our stuff
  106. // by calling savePanel() which will take the values from the CNTL templates.
  107.  
  108.         savePanel(theDialog, toPanel);
  109.         
  110. // need to to find "Chicago" in the font popup, or we will start out with the
  111. // first font in the popup.  Want to start with the standard system font.
  112.  
  113.         if(toPanel == BUTTONS) {
  114.             gFontNum = systemFont;
  115.             gFontSize = 0;
  116.             gButtonValues[12] = 12;
  117.             gButtonValues[13] = findSystemFont(theDialog);
  118.         }
  119.         
  120. // restore control settings and initialize the panel.
  121.  
  122.         restorePanel(theDialog, toPanel);
  123.         currPanel = toPanel;
  124.         
  125. // show the dialog and start handling events
  126.  
  127.         ShowWindow(theDialog);
  128.         
  129.         do {
  130.         
  131.             movableModalDialog    ((ModalFilterProcPtr)filter,&itemHit);
  132.             
  133. // a click on a tab, change to that panel
  134.  
  135.             if(itemHit == TABCNTL) {
  136.             
  137.                 toPanel = daGetCtlValue(theDialog, TABCNTL);
  138.                 
  139.                 if(toPanel != currPanel) {
  140.                 
  141. // save settings of current panel first
  142.         
  143.                     savePanel(theDialog, currPanel);
  144.                 
  145. // switch to the new panel and restore/initialize it.  Since we are using
  146. // the dimText.c routines with AppendDITL, dispose of the dim data stuff.
  147.  
  148.                     disposeDimData(theDialog);
  149.                     panelSwap(theDialog, 128, currPanel, toPanel, STDCTLS);
  150.                     makeDimmable(theDialog);
  151.  
  152.                     restorePanel(theDialog, toPanel);
  153.                 
  154.                     currPanel = toPanel;
  155.                 
  156. // re-enable the Disable/Enable button if needed
  157.  
  158.                     if(!dimIt) {
  159.                         daDimOne(theDialog, DISABLE, false);
  160.                         daSetCtlTitle(theDialog, DISABLE, "\pDisable");
  161.                         dimIt = true;
  162.                     }
  163.                 }
  164.             }
  165.             else
  166.  
  167. // show what the disabled controls look like
  168.  
  169.             if(itemHit == DISABLE) {
  170.                 if(dimIt)
  171.                     daSetCtlTitle(theDialog, DISABLE, "\pEnable");
  172.                 else
  173.                     daSetCtlTitle(theDialog, DISABLE, "\pDisable");
  174.                 inx = CountDITL(theDialog);
  175.                 daDimItems(theDialog, STDCTLS+1, inx, dimIt);
  176.                 dimIt = !dimIt;
  177.                 if(currPanel == BUTTONS)
  178.                     daDimOne(theDialog, PB1, true);
  179.             }
  180.             else
  181.             
  182. // handle a click on some other control within the panel
  183.  
  184.                 processPanel(theDialog, currPanel, itemHit);
  185.                 
  186.         }while(itemHit != ok && itemHit != cancel);
  187.     
  188.         if(itemHit == OK) {
  189. //            savePanel(theDialog, currPanel);
  190. //    some code to apply the temporary storage control values
  191. //    in your application could go here.
  192.  
  193.         }    
  194.         disposeDimText(theDialog);
  195.         DisposDialog(theDialog);
  196.         SetPort(savePort);
  197.     }
  198. }
  199.  
  200. //=============================================================================
  201. // Handle a click on a control
  202. //=============================================================================
  203. static void processPanel(DialogPtr theDialog, short currPanel, short itemHit)
  204. {
  205.     ControlHandle        h;
  206.     short                t;
  207.     Rect                r;
  208.     long                num, newSize;
  209.     Str255                fontSize;
  210.     unsigned long        secs;
  211.     popUpPrivateDataH    hPpd;
  212.     
  213.     switch (currPanel) {
  214.         case BUTTONS:
  215.             switch(itemHit) {
  216.                 case CB1:                // click on a checkBox
  217.                 case CB2:
  218.                 case CB3:
  219.                 case CB4:
  220.                     daToggleCheck(theDialog, itemHit);
  221.                     resetTogButtons(theDialog,TB1);
  222.                 break;
  223.                 case RB1:                // click on a radioButton
  224.                 case RB2:
  225.                 case RB3:
  226.                 case RB4:
  227.                     daToggleRadio(theDialog, itemHit, RB1, RB4);
  228.                     resetTogButtons(theDialog,TB1);
  229.                 break;
  230.                 case TB1:                // click on a TogButton
  231.                 case TB2:
  232.                 case TB3:
  233.                 case TB4:
  234.                     setTogButtons(theDialog, itemHit, TB1, TB4);
  235.                 break;
  236.                 case EDITSIZE:            // keydown in edit text
  237.                     num = daGetINum(theDialog, EDITSIZE);
  238.                     adjustSizePopup(theDialog, num);
  239.                     resetTogButtons(theDialog,TB1);
  240.                 break;
  241.                 case SIZEPOP:
  242.                     GetDItem(theDialog,SIZEPOP,&t,(Handle *)&h,&r);
  243.                     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  244.                     
  245.                     newSize = GetCtlValue(h);
  246.                     GetItem((*hPpd)->mHandle, newSize, fontSize);
  247.                     daSetIText(theDialog, EDITSIZE, fontSize);
  248.                     daSelIText(theDialog, EDITSIZE);
  249.                     resetTogButtons(theDialog,TB1);
  250.                 break;
  251.                 case SETFONT:
  252.                     setNewFont(theDialog);
  253.                     resetTogButtons(theDialog,TB1);
  254.                 break;
  255.             }
  256.         break;
  257.  
  258. // set the value of the arrow control to match the edit text item
  259.  
  260.         case SPINNERS:
  261.             if(itemHit == EDITSPIN) {
  262.                 num = daGetINum(theDialog, EDITSPIN);
  263.                 daSetCtlValue(theDialog, SPIN3, (short)num);
  264.             }
  265.         break;
  266.         
  267. // reset the date time controls if RESET button clicked
  268.  
  269.         case DATETIME:
  270.             if(itemHit == RESET) {
  271.                 GetDateTime(&secs);                        // new date/time
  272.                 for(t=1;t<=6;t++) {
  273.                     h = daGetCtlHandle(theDialog, t+STDCTLS);
  274.                     if(h) {
  275.                         SetCRefCon(h, secs);            // tell control about it
  276.                         InvalRect(&(**h).contrlRect);    // force redraw
  277.                     }
  278.                 }
  279.             }
  280.         break;
  281.         
  282. // show how a spinner control can adjust a progress bar control
  283.  
  284.         case PROGBARS:
  285.             if(itemHit == SPIN10) {
  286.                 daSetCtlValue(theDialog, PROG9, 
  287.                     daGetCtlValue(theDialog, SPIN10));
  288.             }
  289.         break;
  290.         
  291. // we don't do any special processing here for the other control examples,
  292. // but we do some special stuff for sliders via SetControlAction.
  293.  
  294.         case POPUPS:
  295.         break;
  296.         case HSLIDERS:
  297.         break;
  298.         case VSLIDERS:
  299.         break;
  300.     }
  301. }
  302. //=============================================================================
  303. // A sample routine to show one method of saving the settings of the controls
  304. // on a panel. When a panel is "dismissed", the Dialog Manager disposes of the 
  305. // controls on the panel, so we have to save the values to restore if the panel
  306. // is displayed again.
  307. //
  308. // This is pretty "brute force" - just some global arrays of control values.
  309. //
  310. //=============================================================================
  311. static void savePanel(DialogPtr theDialog, short currPanel)
  312. {
  313.     ControlHandle    h;
  314.     Rect            r;
  315.     short            t,inx;
  316.     
  317.     switch (currPanel) {
  318.         case BUTTONS:
  319.             for(inx=1;inx<=BUTTONCNT-2;inx++)
  320.                 gButtonValues[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  321.             gButtonValues[12] = daGetINum(theDialog, EDITSIZE);
  322.             gButtonValues[13] = daGetCtlValue(theDialog, FONTPOP);
  323.         break;
  324.         case POPUPS:
  325.             for(inx=1;inx<=POPUPCNT;inx++)
  326.                 gPopUpValues[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  327.         break;
  328.         case SPINNERS:
  329.             for(inx=1;inx<=SPINNERCNT;inx++)
  330.                 gSpinnerValues[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  331.         break;
  332.         case DATETIME:
  333.             for(inx=1;inx<=DATECNT;inx++)
  334.                 gDateValues[inx-1] = daGetCtlRefCon(theDialog, inx+STDCTLS);
  335.         break;
  336.         case HSLIDERS:
  337.             for(inx=1;inx<=HSLIDERCNT;inx++)
  338.                 gHSliderValues[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  339.         break;
  340.         case VSLIDERS:
  341.             for(inx=1;inx<=VSLIDERCNT;inx++)
  342.                 gVSliderValues[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  343.         break;
  344.         case PROGBARS:
  345.             for(inx=1;inx<=PROGBARCNT;inx++)
  346.                 gProgressValues[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  347.         break;
  348.         case POPUPEXT:
  349.             for(inx=1;inx<=POPEXTCNT;inx++)
  350.                 gPopExtensions[inx-1] = daGetCtlValue(theDialog, inx+STDCTLS);
  351.         break;
  352.     }
  353. }
  354.  
  355. //=============================================================================
  356. // A sample routine to show one method of restoring the control settings to
  357. // proper values when a panel is shown by clicking on its tab.
  358. //
  359. // This routine also does some special initialization of controls.
  360. //=============================================================================
  361. static void restorePanel(DialogPtr theDialog, short toPanel)
  362. {
  363.     ControlHandle    ch;
  364.     SpinHandle        hSpin;
  365.     Rect            r;
  366.     short            t,inx;
  367.     long            l;
  368.  
  369.     switch(toPanel) {
  370.     
  371.         case BUTTONS:
  372.             
  373. // set font & restore control values
  374.             
  375.             changeFont(theDialog, gFontNum, gFontSize);
  376.             for(inx=1;inx<=BUTTONCNT-2;inx++)
  377.                 daSetCtlValue(theDialog, inx+STDCTLS, gButtonValues[inx-1]);
  378.  
  379. // set font controls
  380.  
  381.             daSetINum(theDialog, EDITSIZE, gButtonValues[12]);
  382.             adjustSizePopup(theDialog, gButtonValues[12]);
  383.             daSetCtlValue(theDialog, FONTPOP, gButtonValues[13]);
  384.                 
  385. // initialize the Tog buttons and disable one button
  386.  
  387.             initTogButtons(theDialog, TB1,TB4);
  388.             daDimOne(theDialog, PB1, true);
  389.         break;
  390.         
  391.         case POPUPS:
  392.         
  393. // set font & restore control values
  394.  
  395.             changeFont(theDialog, geneva, 9);
  396.             for(inx=1;inx<=POPUPCNT;inx++)
  397.                 if(gPopUpValues[inx-1])
  398.                     daSetCtlValue(theDialog, inx+STDCTLS, gPopUpValues[inx-1]);
  399.         break;
  400.         
  401.         case SPINNERS:
  402.         
  403. // set font & restore control values
  404.             
  405.             changeFont(theDialog, 0, 0);        // since there is an edit field
  406.             
  407.             for(inx=1;inx<=SPINNERCNT;inx++)
  408.                 daSetCtlValue(theDialog, inx+STDCTLS, gSpinnerValues[inx-1]);
  409.             
  410. // initialize edit text item to the value of the 3rd spinner
  411.  
  412.             daSetINum(theDialog, EDITSPIN, 
  413.                         daGetCtlValue(theDialog,  SPIN3));
  414.             SelIText(theDialog, EDITSPIN, 32768, 32768);
  415.             
  416. // the 6th spinner will adjust by 0.10, so stash a divisor value of 10
  417. // in the userData field
  418.  
  419.             ch = daGetCtlHandle(theDialog, SPIN7);
  420.             if(ch) {
  421.                 hSpin = (SpinHandle)(**ch).contrlData;
  422.                 (**hSpin).userData = 10;
  423.                 fractSpin(ch, 1);                // draw the value
  424.             }
  425.             
  426.         break;
  427.         
  428.         case DATETIME:
  429.  
  430. // set font & restore control values
  431.  
  432.             changeFont(theDialog, geneva, 9);
  433.             for(inx=1;inx<=DATECNT;inx++)
  434.                 daSetCtlRefCon(theDialog, inx+STDCTLS, gDateValues[inx-1]);
  435.         break;    
  436.         
  437.         case HSLIDERS:
  438.  
  439. // set font & restore control values
  440.  
  441.             changeFont(theDialog, geneva, 9);
  442.             for(inx=1;inx<=HSLIDERCNT;inx++)
  443.                 daSetCtlValue(theDialog, inx+STDCTLS, gHSliderValues[inx-1]);
  444.                 
  445. // set a ctlAction proc for slider 3
  446.             
  447.             ch = daGetCtlHandle(theDialog, HSLIDER3);
  448. #ifdef NEW_HEADERS_AVAILABLE
  449.             SetCtlAction(ch, (ControlActionUPP)trackSlider);
  450. #else
  451.             SetCtlAction(ch, (ProcPtr)trackSlider);
  452. #endif
  453.             daSetINum(theDialog, HSLIDERVAL, GetCtlValue(ch));
  454.         break;    
  455.         
  456.         case VSLIDERS:
  457.             changeFont(theDialog, geneva, 9);
  458.  
  459. // restore control values
  460.  
  461.             for(inx=1;inx<=VSLIDERCNT;inx++)
  462.                 daSetCtlValue(theDialog, inx+STDCTLS, gVSliderValues[inx-1]);
  463.                 
  464. // set a ctlAction proc for slider 5
  465.             
  466.             ch = daGetCtlHandle(theDialog, VSLIDER5);
  467. #ifdef NEW_HEADERS_AVAILABLE
  468.             SetCtlAction(ch, (ControlActionUPP)trackSlider);
  469. #else
  470.             SetCtlAction(ch, (ProcPtr)trackSlider);
  471. #endif
  472.             daSetINum(theDialog, VSLIDERVAL, GetCtlValue(ch));
  473.         break;    
  474.         
  475.         case PROGBARS:
  476.         
  477. // set font & restore control values
  478.  
  479.             changeFont(theDialog, geneva, 9);
  480.             for(inx=1;inx<=PROGBARCNT;inx++)
  481.                 daSetCtlValue(theDialog, inx+STDCTLS, gProgressValues[inx-1]);
  482.         break;    
  483.         case POPUPEXT:
  484.             changeFont(theDialog, 0, 0);
  485.             for(inx=1;inx<=POPEXTCNT;inx++)
  486.                 daSetCtlValue(theDialog, inx+STDCTLS, gPopExtensions[inx-1]);
  487.         break;
  488.     }
  489. }
  490. //=============================================================================
  491. //    a simple dialog filter proc
  492. //=============================================================================
  493. static  pascal char filter(DialogPtr theDialog, EventRecord *theEvent, short *theItem)
  494. {
  495.     char             result = FALSE;
  496.     char             c;
  497.     short            panelNum,inx,editItem,partCode;
  498.     long            min,max;
  499.     ControlHandle    cHdl;
  500.     Point            mousePt;
  501.     
  502.     switch(theEvent->what) {
  503.         
  504.         panelNum = daGetCtlValue(theDialog, TABCNTL);
  505.         
  506.         case nullEvent:
  507.         
  508. // for this demo program, we'll use null events to demo the progress bar
  509. // cdefs on panel 7 of the dialog
  510.  
  511.             if(panelNum == PROGBARS) {
  512.                 for(inx=STDCTLS+1;inx<=STDCTLS+8;inx++) {
  513.                     daSetCtlValue(theDialog, inx, 
  514.                                     daGetCtlValue(theDialog, inx)+1);
  515.                     if(daGetCtlValue(theDialog, inx) >= daGetCtlMax(theDialog, inx))
  516.                         daSetCtlValue(theDialog, inx, 0);
  517.                 }
  518.             }
  519.         break;
  520.  
  521.         
  522.         case keyDown:
  523.          case autoKey:
  524.  
  525. // for this demo, we'll show how to use command or control key 
  526. // combinations to operate the tabPanel CDEF
  527.  
  528.              c = theEvent->message & charCodeMask;
  529.              
  530.             if(theEvent->modifiers & cmdKey) {
  531.                  if(result = panelCmdKey(theDialog, TABCNTL, c, theItem))
  532.                      break;
  533.              }
  534.             if(theEvent->modifiers & controlKey ||
  535.                 theEvent->modifiers & cmdKey) {
  536.                  if(result = panelCmdTab(theDialog, TABCNTL, c, theItem))
  537.                      break;
  538.              }
  539.              if(result = daExitKey(theDialog, theEvent, theItem, cancel))
  540.                  break;
  541.  
  542. // handle a forward delete key
  543.                  
  544.              if(result = daForwardDel(theDialog, c))
  545.                  break;
  546.              if(theEvent->modifiers & shiftKey) {
  547.                  if(result = daShiftSelect(theDialog, c))
  548.                      break;
  549.              }
  550.             editItem = ((DialogPeek)theDialog)->editField + 1;
  551.             
  552. // limit to numeric entry only
  553.  
  554.             if(panelNum == BUTTONS && editItem == EDITSIZE) {
  555.                 result = daEnterNumber(theDialog, editItem, 0L, 18L, c);
  556.             }
  557.             else 
  558.             if(panelNum == SPINNERS) {
  559.                 max = daGetCtlMax(theDialog, SPIN3);
  560.                 min = daGetCtlMin(theDialog, SPIN3);
  561.                 result = daEnterNumber(theDialog, editItem, min, max, c);
  562.             }
  563.          break;
  564.          
  565.          case mouseDown:
  566.             mousePt = theEvent->where;
  567.             GlobalToLocal(&mousePt);
  568.             partCode = FindControl(mousePt, theDialog, &cHdl);
  569.  
  570.  // demonstrate use of FindControl/TrackControl within a dialog and to show
  571.  // how to continuously update the progress bar (item #10) from the value 
  572.  // of the spinner (item #9)
  573.  
  574.              if(panelNum == PROGBARS) {
  575.                 if(partCode && cHdl == daGetCtlHandle(theDialog, SPIN10)) {
  576. #ifdef NEW_HEADERS_AVAILABLE
  577.                     TrackControl(cHdl, mousePt,  (ControlActionUPP)trackSpin);
  578. #else
  579.                     TrackControl(cHdl, mousePt,  (ProcPtr)trackSpin);
  580. #endif
  581.                 }
  582.              }
  583.              else
  584.  
  585.  // spinner 6 is a control that adjusts by a fractional value
  586.  
  587.              if(panelNum == SPINNERS) {
  588.                 if(partCode && cHdl == daGetCtlHandle(theDialog, SPIN7)) {
  589. #ifdef NEW_HEADERS_AVAILABLE
  590.                     TrackControl(cHdl, mousePt,  (ControlActionUPP)fractSpin);
  591. #else
  592.                     TrackControl(cHdl, mousePt,  (ProcPtr)fractSpin);
  593. #endif
  594.                 }
  595.              }
  596.      
  597.          break;
  598.     }
  599.     return result;
  600. }
  601. //=============================================================================
  602. //    A simple action proc for call to TrackControl above.  Just sets the value
  603. //  of the progress bar to match the spinner.
  604.  
  605. //=============================================================================
  606. static pascal void trackSpin(ControlHandle theControl, short partCode)
  607. {
  608.     DialogPtr theDialog = (**theControl).contrlOwner;
  609.     
  610.     if(partCode) {
  611.         daSetCtlValue(theDialog, PROG9, GetCtlValue(theControl));
  612.     }
  613. }
  614. //=============================================================================
  615. //    This routine is set as an actionProc via SetCtlAction to provide
  616. //  "live" display of the values of a Slider control
  617.  
  618. //=============================================================================
  619. static pascal void trackSlider(ControlHandle theControl, short partCode)
  620. {
  621.     DialogPtr theDialog = (**theControl).contrlOwner;
  622.     
  623.     if(partCode) {
  624.         if(theControl == daGetCtlHandle(theDialog, VSLIDER5))
  625.             daSetINum(theDialog, VSLIDERVAL, GetCtlValue(theControl));
  626.         else
  627.         if(theControl == daGetCtlHandle(theDialog, HSLIDER3))
  628.             daSetINum(theDialog, HSLIDERVAL, GetCtlValue(theControl));
  629.     }
  630. }
  631. //=============================================================================
  632. //    This Action proc shows how to have a spinner control with a fractional
  633. //  increment
  634.  
  635. //=============================================================================
  636. static pascal void fractSpin(ControlHandle theControl, short partCode)
  637. {
  638.     DialogPtr        theDialog;
  639.     short            val,div;
  640.     ControlHandle    hCtrl;
  641.     SpinHandle        hSpin;
  642.     Str255            s;
  643.     double            dbl;
  644.     
  645.     if(!partCode)                    // avoid flicker
  646.         return;
  647.         
  648.     theDialog = (**theControl).contrlOwner;
  649.     
  650. // grab the handle to the control, extract the userData value
  651. // to use as divisor to calculate the value to display in the text item
  652.  
  653.     hCtrl = daGetCtlHandle(theDialog, SPIN7);
  654.     if(theControl == hCtrl) {
  655.         hSpin = (SpinHandle)(**theControl).contrlData;
  656.         div = (**hSpin).userData;
  657.         
  658.         val = GetCtlValue(hCtrl);
  659.         dbl = (double)val/div;
  660.         
  661.         sprintf((char *)s, "%3.1lf", dbl);
  662.         CtoPstr((char *)s);
  663.         
  664. // display the calcuated value (in this case, via a statText item)
  665.  
  666.         daSetIText(theDialog, FRACTSPIN, s);
  667.     }
  668.         
  669. }
  670.  
  671. //=============================================================================
  672. // Get font & font size info from panel 1 controls and use to change font.
  673. //=============================================================================
  674. static void setNewFont (DialogPtr theDialog)
  675. {
  676.     ControlHandle        h;
  677.     short                t, val, newFont;
  678.     Rect                r;
  679.     long                num, newSize;
  680.     Str255                fontName, fontSize;
  681.     GrafPtr                thisPort;
  682.     popUpPrivateDataH    hPpd;
  683.  
  684. // get the font size from the popup menu
  685.  
  686.     GetDItem(theDialog,SIZEPOP,&t,(Handle *)&h,&r);
  687.     val = GetCtlValue(h);
  688.     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  689.     GetItem((*hPpd)->mHandle, val, fontSize);
  690.     StringToNum(fontSize, &newSize);
  691.     if(newSize == 12)
  692.         newSize = 0;
  693.  
  694. // get the font from the popup menu
  695.     
  696.     GetDItem(theDialog,FONTPOP,&t,(Handle *)&h,&r);
  697.     val = GetCtlValue(h);
  698.     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  699.     GetItem((*hPpd)->mHandle, val, fontName);
  700.     GetFNum(fontName, &newFont);
  701.     
  702.     changeFont(theDialog, newFont, newSize);
  703.     
  704.     GetPort(&thisPort);
  705.     gFontNum = thisPort->txFont;
  706.     gFontSize = thisPort->txSize;
  707.  
  708. // redraw the dialog in the new font & size
  709.  
  710.         DrawDialog(theDialog);
  711. }
  712.  
  713. //=============================================================================
  714. //    Set a new font for this dialog.  This is a nasty way to do this,
  715. //  but it appears to work.
  716.  
  717. //=============================================================================
  718. static void changeFont(DialogPtr theDialog, short newFont, long newSize)
  719. {
  720.     FontInfo        fInfo;
  721.     
  722.     SetPort(theDialog);
  723.     
  724.     if(theDialog->txFont != newFont ||                // minimize flicker from
  725.         theDialog->txSize != newSize) {                // redrawing
  726.         
  727. // set new font & size for current port
  728.         
  729.         TextFont(newFont);
  730.         TextSize((short)newSize);
  731.         
  732. // set new font for TEHandle in dialog (this is a crude hack!)
  733.         
  734.         GetFontInfo(&fInfo);
  735.         (*((DialogPeek)theDialog)->textH)->txFont = newFont;
  736.         (*((DialogPeek)theDialog)->textH)->txSize = newSize;
  737.         (*((DialogPeek)theDialog)->textH)->fontAscent = fInfo.ascent;
  738.     }
  739. }
  740.  
  741. //=============================================================================
  742. //    Set a new size into the popup menu for font size.  Called when the 
  743. //    EDITSIZE dialog edit item is changed, will add or remove a "custom" size
  744. //    and a separator line as required.
  745.  
  746. //=============================================================================
  747. static void    adjustSizePopup    (DialogPtr theDialog, long newSize)
  748. {
  749.     short                type,val,inx,max;
  750.     long                longVal;
  751.     ControlHandle        h;
  752.     MenuHandle            hMenu;
  753.     Rect                r;
  754.     popUpPrivateDataH    hPpd;
  755.     Str255                s;
  756.     Boolean                found=false;
  757.     
  758.     GetDItem(theDialog,SIZEPOP,&type,(Handle *)&h,&r);    // get menu handle
  759.     hPpd = (popUpPrivateDataH)(*h)->contrlData;
  760.     hMenu = (*hPpd)->mHandle;
  761.     
  762.     val = GetCtlValue(h);                                // uncheck current item
  763.     CheckItem(hMenu, val, FALSE);
  764.     
  765.     max = CountMItems(hMenu);                            // number of menu items
  766.     
  767.     for(inx=1;inx<=max;inx++) {                            // see if typed in value
  768.         GetItem(hMenu, inx, s);                            // matches a menu item
  769.         StringToNum(s, &longVal);
  770.         if(longVal == newSize) {                        // yep, got a match but it is
  771.             if(inx > 2 & max > MAXFONTSIZES) {            // not custom, so let's
  772.                 DelMenuItem(hMenu,1);                    // delete the custom setting
  773.                 DelMenuItem(hMenu,1);                    // and the separator line
  774.                 inx-=2;
  775.             }
  776.             CheckItem(hMenu, inx, TRUE);                // check new item
  777.             SetCtlValue(h, inx);
  778.             found = true;
  779.             break;
  780.         }
  781.     }
  782.     if(!found) {                                        // no match, set custom item
  783.         NumToString(newSize, s);
  784.         if(max == MAXFONTSIZES) {                        // add a custom value
  785.             InsMenuItem(hMenu, "\p(-", 0);                // first, a separator
  786.             InsMenuItem(hMenu, s, 0);                    // now, the new size
  787.         }
  788.         else {
  789.             SetItem(hMenu, 1, s);                        // replace existing custom
  790.         }
  791.         CheckItem(hMenu, 1, TRUE);
  792.         SetCtlValue(h, 1);
  793.     }
  794. }
  795.  
  796. //=============================================================================
  797. // find the System font item in the popup menu created with AddResMenu
  798. //=============================================================================
  799. static short findSystemFont(DialogPtr theDialog)
  800. {
  801.     Str255                fontName;
  802.     ControlHandle        hCtl;
  803.     MenuHandle            hMenu;
  804.     short                t,max,inx,newFont=2;
  805.     Rect                r;
  806.     popUpPrivateDataH    hPpd;
  807.     
  808.     GetDItem(theDialog, FONTPOP, &t, (Handle *)&hCtl, &r);
  809.     if(hCtl) {
  810.         hPpd = (popUpPrivateDataH)(*hCtl)->contrlData;
  811.         hMenu = (*hPpd)->mHandle;
  812.         if(hMenu) {
  813.             max = CountMItems(hMenu);
  814.         
  815.             for(inx=1;inx<=max;inx++) {
  816.                 GetItem(hMenu, inx, fontName);
  817.                 GetFNum(fontName, &newFont);
  818.                 if(newFont == systemFont)
  819.                     break;
  820.                     
  821.             }
  822.         }
  823.     }
  824.     return(inx);
  825. }
  826.  
  827. //=============================================================================
  828. // a simple side-by-side comparison between CDEF 63 (System 7) & CDEF 101
  829. //=============================================================================
  830. extern void comparePopup()
  831. {
  832.     DialogPtr        theDialog;
  833.     GrafPtr            savePort;
  834.     short            itemHit,inx,t;
  835.     ControlHandle    hCtl,hCtl2;
  836.     Rect            r;
  837.     
  838.     theDialog = GetNewDialog(259,0L,(DialogPtr)-1);
  839.     if(theDialog) {
  840.         GetPort(&savePort);
  841.         SetPort(theDialog);
  842.         TextFont(monaco);
  843.         TextSize(9);
  844.         ShowWindow(theDialog);
  845.         
  846.         do {
  847.             movableModalDialog ((ModalFilterProcPtr)filterCompare,&itemHit);
  848.             if(itemHit == 3) {        // disable button
  849.                 for(inx = 4;inx<=15;inx++) {
  850.                     GetDItem(theDialog, inx, &t, (Handle *)&hCtl, &r);
  851.                         if((*hCtl)->contrlHilite == 0xff)
  852.                             HiliteControl(hCtl,0);
  853.                         else
  854.                             HiliteControl(hCtl,255);
  855.                 }
  856.                 GetDItem(theDialog, 3, &t,(Handle *)&hCtl2, &r);
  857.                 if((*hCtl)->contrlHilite == 0xff)
  858.                     SetCTitle(hCtl2, "\pEnable");
  859.                 else
  860.                     SetCTitle(hCtl2, "\pDisable");
  861.             }        
  862.         }while(itemHit != ok && itemHit != cancel);
  863.         DisposDialog(theDialog);
  864.         SetPort(savePort);
  865.     }
  866. }
  867.  
  868. static pascal char    filterCompare    (DialogPtr theDialog, EventRecord *theEvent, 
  869.                                         short *theItem)
  870. {
  871.     char             result = FALSE;
  872.     
  873. // just check for an exit key, really should put this into movableModal...
  874.  
  875.     switch(theEvent->what) {
  876.         case keyDown:
  877.          case autoKey:
  878.              if(result = daExitKey(theDialog, theEvent, theItem, cancel))
  879.                  break;
  880.          break;
  881.      }
  882.      return(result);
  883. }
  884.